﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024-2025 LiLong                                              **
**  This file is part of OpenVisaApplication.                                   **
**                                                                              **
**  OpenVisaApplication is free software: you can redistribute it and/or modify **
**  it under the terms of the GNU General Public License as published by        **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  OpenVisaApplication is distributed in the hope that it will be useful,      **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU General Public License for more details.                                **
**                                                                              **
**  You should have received a copy of the GNU General Public License           **
**  along with OpenVisaApplication. If not, see <https://www.gnu.org/licenses/>.**
**********************************************************************************/
#include "DeviceGroup.h"
#include "Device.h"

#include <algorithm>

namespace AppCore
{
struct DeviceGroup::Impl
{
    std::vector<std::shared_ptr<DeviceItem>> items;
};

DeviceGroup::DeviceGroup() : m_impl(std::make_unique<Impl>()) {}

DeviceGroup::~DeviceGroup() {}

void DeviceGroup::addChild(std::shared_ptr<DeviceItem> child)
{
    m_impl->items.push_back(child);
    child->setParent(std::dynamic_pointer_cast<DeviceGroup>(this->shared_from_this()));
}

const std::vector<std::shared_ptr<DeviceItem>>& DeviceGroup::children() const { return m_impl->items; }

void DeviceGroup::removeChild(int index)
{
    if (index < 0)
        return;
    m_impl->items.erase(m_impl->items.begin() + index);
}

void DeviceGroup::clear() { m_impl->items.clear(); }

int DeviceGroup::indexOf(std::shared_ptr<DeviceItem> child) const
{
    auto it = std::ranges::find(m_impl->items, child);
    return it == m_impl->items.end() ? -1 : std::distance(m_impl->items.begin(), it);
}

void DeviceGroup::sort()
{
    std::ranges::sort(m_impl->items, [](auto a, auto b) { return a->name() < b->name(); });
}

bool NetworkGroup::contains(const QString& address) const
{
    return std::ranges::any_of(children(), [&](auto dev) { return dev->address() == address; });
}

bool SerialPortGroup::contains(const QString& portName) const
{
    return std::ranges::any_of(children(),
                               [&](auto dev)
                               {
                                   auto sp = dynamic_pointer_cast<AppCore::SerialPortDevice>(dev);
                                   return sp->portName() == portName;
                               });
}

bool UsbTmcGroup::contains(uint16_t vid, uint16_t pid, const QString& sn) const
{
    return std::ranges::any_of(children(),
                               [&](auto dev)
                               {
                                   auto usb = dynamic_pointer_cast<AppCore::UsbTmcDevice>(dev);
                                   return usb->vendorId() == vid && usb->productId() == pid && usb->serialNumber() == sn;
                               });
}

} // namespace AppCore